package com.itzxx.huazhun.ui.collection.read

import android.text.TextUtils
import cn.com.heaton.blelibrary.ble.model.BleDevice
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import com.itzxx.huazhun.data.dao.CollectionEntity
import com.itzxx.huazhun.data.dao.DbHelper
import com.itzxx.huazhun.data.dao.ProbeRecordEntity
import com.itzxx.huazhun.data.model.CoordinatorInfo
import com.itzxx.huazhun.data.model.EventMessage
import com.itzxx.huazhun.data.model.EventType
import com.itzxx.huazhun.data.model.ProbeAllInfo
import com.itzxx.huazhun.data.model.ProbeInfo
import com.itzxx.huazhun.data.model.ProbeStateInfo
import com.itzxx.huazhun.data.model.ProbeTestingInfo
import com.itzxx.huazhun.data.repository.HttpRequestCoroutine
import com.itzxx.huazhun.utils.UserCacheHelper
import com.itzxx.huazhun.utils.ble.BleConstant
import com.itzxx.huazhun.utils.ble.BleHelper
import com.itzxx.huazhun.utils.ble.BleListener
import com.itzxx.huazhun.utils.ble.BleRequestData
import com.itzxx.huazhun.utils.ble.BleWriteListener
import com.itzxx.library_base_ktx.base.viewmodel.BaseViewModel
import com.itzxx.library_base_ktx.callback.databind.BooleanObservableField
import com.itzxx.library_base_ktx.callback.livedata.event.EventLiveData
import com.itzxx.library_base_ktx.ext.request
import com.itzxx.library_base_ktx.ext.util.loge
import kotlinx.coroutines.DelicateCoroutinesApi
import org.greenrobot.eventbus.EventBus
import org.json.JSONObject
import java.math.BigDecimal
import java.math.RoundingMode
import java.util.Timer
import java.util.TimerTask


class ReadCollectionDataViewModel : BaseViewModel() {

    private var checkBleDevice: BleDevice? = null
    private var mBleListener: BleListener? = null


    val probeOneState = BooleanObservableField(true)
    val probeTwoState = BooleanObservableField(true)
    val probeThreeState = BooleanObservableField(true)
    val probeFourState = BooleanObservableField(true)
    val probeListState = EventLiveData<List<ProbeStateInfo>>()
    val readCollectionBtn = BooleanObservableField(false)

    //准备获取全部信息的队列
    val queueProbeAllInfo = ArrayDeque<ProbeAllInfo>()
    //上传数据队列
    val queueCollectionEntity= ArrayDeque<CollectionEntity>()

    //读取完成数据
    val readProbeAllInfoEndList = mutableListOf<ProbeAllInfo>()

    //准备获取全部探头状态信息
    val queueProbeStateInfo = ArrayDeque<ProbeStateInfo>()

    //准备获取全部探头采集信息
    val queueProbeTestingStateInfo = ArrayDeque<ProbeInfo>()

    //当前正在采集的
    lateinit var currentTestingProbeAllInfo: ProbeAllInfo

    //定时器
    val timer = Timer()

    @OptIn(ExperimentalUnsignedTypes::class, DelicateCoroutinesApi::class)
    override fun onCreateViewModel() {
        super.onCreateViewModel()
        //当前选中的数据
        checkBleDevice = BleHelper.getConnectBleDevice()
        //当前连接的设备
        if (checkBleDevice == null && BleHelper.getBleBaseDevices().isNotEmpty()) {
            checkBleDevice = BleHelper.getBleBaseDevices()[0]
        }
        mBleListener = object : BleListener() {
            override fun onEnableDataNotify(type: UByte, json: String) {
                super.onEnableDataNotify(type, json)
                "收到硬件数据>>>>>onChanged:${json}".loge()
                when (type) {
                    // 获取协调器信息
                    BleConstant.Cmd.GET_COORDINATOR_INFO_RESPONSE -> {
                        val currentInfo = Gson().fromJson(json, CoordinatorInfo::class.java)
                        val probeInfoList = Gson().fromJson<MutableList<ProbeStateInfo>>(
                            currentInfo.probe,
                            object : TypeToken<MutableList<ProbeStateInfo>>() {}.type
                        )
                        probeInfoList.forEach {
                            when (it.holeIndex) {
                                "01" -> {
                                    probeOneState.set(false)
                                }

                                "02" -> {
                                    probeTwoState.set(false)
                                }

                                "03" -> {
                                    probeThreeState.set(false)
                                }

                                "04" -> {
                                    probeFourState.set(false)
                                }
                            }
                        }
                        val probeList = mutableListOf<ProbeStateInfo>()
                        for (index in 0..3) {
                            probeList.add(ProbeStateInfo(holeIndex = (index + 1).toString()))
                        }
                        probeListState.postValue(probeList)
                        if (probeInfoList.isNotEmpty()) {
                            loadingChange.showDialog.postValue("获取探头信息中...")
                            probeInfoList.forEachIndexed { index, probeStateInfo ->
                                //默认采集中，因为两秒没返回就是在采集中
                                probeList[probeStateInfo.holeIndex.toInt() - 1].probeMac =
                                    probeStateInfo.probeMac
                                queueProbeStateInfo.add(probeStateInfo)
                                probeListState.postValue(probeList)
                            }
                            sendProbeInfoCommand()
                        }
                    }

                    //获取探头信息
                    BleConstant.Cmd.GET_PROBE_INFO_RESPONSE -> {
                        //返回探头信息
                        val probeInfo = Gson().fromJson(json, ProbeInfo::class.java)
                        probeListState.value?.let {
                            for (item in it) {
                                //遍历返回数据设置状态和数据
                                if (TextUtils.equals(probeInfo.mac, item.probeMac)) {
                                    //默认状态没问题，就绪状态
                                    item.state = 1
                                    item.probeInfo = probeInfo
                                    item.serialNumber = probeInfo.model.replace("XHD-D", "")
                                    break
                                }
                            }
                            probeListState.postValue(it)
                        }
                        //为探头采集信息数据
                        queueProbeTestingStateInfo.add(probeInfo)
                        sendProbeInfoCommand()
                    }
                    //返回探头采集信息
                    BleConstant.Cmd.READ_SAMPLING_INFO_RESPONSE -> {
                        val jsonObject = JSONObject(json)
                        val mac = jsonObject.optString("mac", "")
                        probeListState.value?.let {
                            for (item in it) {
                                //遍历返回数据设置状态和数据
                                if (TextUtils.equals(mac, item.probeMac)) {
                                    val samplingInfo = jsonObject.optString("samplingInfo", "")
                                    val samplingInfoArray =
                                        Gson().fromJson<MutableList<ProbeTestingInfo>>(
                                            samplingInfo,
                                            object :
                                                TypeToken<MutableList<ProbeTestingInfo>>() {}.type
                                        )
                                    //表示采集间隔为10*100ms = 1S,需要处理一下
//                                    samplingInfoArray[0].recordSamplingInterval = samplingInfoArray[0].recordSamplingInterval
                                    item.probeTestingInfo = samplingInfoArray[0]
                                    //数据库检测是否已经读取完成
                                    val collectionRecord =
                                        DbHelper.init().getCollectionDao()
                                            .getCollectionRecord(
                                                item.probeMac,
                                                samplingInfoArray[0].recordStartTime
                                            )
                                    if (collectionRecord != null) {
                                        item.state = 3
                                    }
                                    break
                                }
                            }
                            probeListState.postValue(it)
                            onAllTestsCompleted(it)
                        }
                        sendProbeTestingInfoCommand()
                    }

                    //返回探头采集数据
                    BleConstant.Cmd.READ_SAMPLING_DATA_RESPONSE -> {
                        val jsonObject = JSONObject(json)
                        val mac = jsonObject.optString("mac", "")
                        if (TextUtils.equals(mac, currentTestingProbeAllInfo.mac)) {
                            val recordData = jsonObject.optString("recordData", "")
                            val probeSamplingRecordInfoList =
                                Gson().fromJson<MutableList<ProbeRecordEntity>>(
                                    recordData,
                                    object :
                                        TypeToken<MutableList<ProbeRecordEntity>>() {}.type
                                )
                            currentTestingProbeAllInfo.probeSamplingRecordInfoList.addAll(
                                probeSamplingRecordInfoList
                            )

                        }
                        //====刷新一下读取完的时间====
                        currentTestingProbeAllInfo.refreshReadTime()
                        //数据完成后刷新数据
                        currentTestingProbeAllInfo.plusRecordStartIndex()
                        if (currentTestingProbeAllInfo.isEndRead()) {
                            "currentTestingProbeAllInfo.isEndRead()=$currentTestingProbeAllInfo.isEndRead()".loge()
                            readProbeAllInfoEndList.add(currentTestingProbeAllInfo)
                            //====读取一个完成先设置状态====
                            probeListState.value?.let {
                                for (item in it) {
                                    //====遍历返回数据设置状态和数据====
                                    if (TextUtils.equals(
                                            currentTestingProbeAllInfo.mac,
                                            item.probeMac
                                        )
                                    ) {
                                        //读取完成状态
                                        item.state = 3
                                        break
                                    }
                                }
                                probeListState.postValue(it)
                                //检测是不是全部完成
                                onAllTestsCompleted(it)
                            }
                            //====判断是否还有数据，如果没有说明读取完成====
                            val removeFirst = queueProbeAllInfo.removeFirstOrNull()
                            if (removeFirst == null) {
                                loadingChange.dismissDialog.postValue(false)
                                //====打印读取完成的数据====
                                readProbeAllInfoEndList.forEach {
                                    "mac地址：${it.mac}".loge()
                                    "采集记录数量：${it.recordNum}".loge()
                                    "读取采集数量：${it.probeSamplingRecordInfoList.size}".loge()
                                }
                                //====读完完成定时检测就关闭====
                                timer.cancel()
                                loadingChange.showDialog.postValue("数据存存储中...")
                                keepDataToSql()
                                return
                            }
                            //====继续采取下一个====
                            currentTestingProbeAllInfo = removeFirst
                        }
                        //====继续发送下一个命令====
                        val macUByteArray = currentTestingProbeAllInfo.mac.split(":")
                            .map { value -> value.toUByte(16) }
                            .toUByteArray()
                        val generateReadSamplingDataRequestData =
                            BleRequestData.generateReadSamplingDataRequestData(
                                macUByteArray,
                                currentTestingProbeAllInfo.getRecordStartIndexNum(),
                                currentTestingProbeAllInfo.getSingleRecordCallBackSize()
                            )
                        BleHelper.writeDelay(generateReadSamplingDataRequestData)
                    }
                }
            }
        }

        //====设置数据监听====
        mBleListener?.let {
            BleHelper.addBleListener(it)
        }
        //====获取底座状态====
        checkBleDevice?.let {
            BleHelper.write(BleRequestData.GET_COORDINATOR_INFO_REQUEST_DATA)
        }
    }

    override fun onPauseViewModel() {
        super.onPauseViewModel()
        mBleListener?.let {
            BleHelper.removeBleListener(it)
        }
    }

    @OptIn(ExperimentalUnsignedTypes::class)
    fun readOnePiece() {
        if (readCollectionBtn.get()) {
            val bean = EventMessage(EventType.SWITCH_MAIN_PAGE, "")
            bean.arg1 = "3"
            EventBus.getDefault().post(bean)
            finish()
            return
        }

        probeListState.value?.run {
            //处理能读取的数据
            var beReadyNum = 0
            //初始化
            queueProbeAllInfo.clear()
            for (item in this) {
                //状态就绪的
                if (item.state == 1) {
                    beReadyNum++
                }
                //有返回采集数据信息
                if (item.state == 1 && item.probeTestingInfo != null) {
                    val probeAllInfo = ProbeAllInfo(
                        item.probeInfo!!.mac,
                        item.probeInfo!!.sw,
                        item.probeInfo!!.hw,
                        item.probeInfo!!.battery,
                        item.probeInfo!!.feature,
                        item.probeInfo!!.wayNum,
                        item.probeInfo!!.wayIndex,
                        item.probeTestingInfo!!.recordSamplingInterval,
                        item.probeTestingInfo!!.recordStartTime,
                        item.probeInfo!!.model,
                        item.probeTestingInfo!!.recordNum,
                    )
                    //开始读取下标
                    probeAllInfo.initReadIndex(item.probeTestingInfo!!.recordStartIndex.toInt())
                    queueProbeAllInfo.add(probeAllInfo)
                }
            }

            if (queueProbeAllInfo.size == 0) {
                toast("未有采集数据")
            } else if (beReadyNum == queueProbeAllInfo.size) {
                //准备开始读取数据
                currentTestingProbeAllInfo = queueProbeAllInfo.removeFirst()
                if (currentTestingProbeAllInfo.recordNum == 0) {
                    toast("采集未开始")
                    return
                }
                //开始采集
                loadingChange.showDialog.postValue("开始读取采集数据...")
                //做检查任务
                timer.schedule(testReadTheResultsTask(), 0, 3000)
            } else {
                toast("蓝牙返回采集数据信息数量异常")
            }
        }
    }

    //定时器任务
    fun testReadTheResultsTask() = object : TimerTask() {
        override fun run() {
            if (currentTestingProbeAllInfo.errorOutLimit()) {
                toast("读取采集数据异常")
                timer.cancel()
                loadingChange.dismissDialog.postValue(false)
            } else if (currentTestingProbeAllInfo.isReadTimeout()) {
                //轮训检测是否超时没返回
                val macUByteArray =
                    currentTestingProbeAllInfo.mac.split(":").map { value -> value.toUByte(16) }
                        .toUByteArray()
                val generateReadSamplingDataRequestData =
                    BleRequestData.generateReadSamplingDataRequestData(
                        macUByteArray,
                        currentTestingProbeAllInfo.getRecordStartIndexNum(),
                        currentTestingProbeAllInfo.getSingleRecordCallBackSize()
                    )
                BleHelper.writeDelay(generateReadSamplingDataRequestData)
            }
        }
    }

    //保存到数据数据库
    fun keepDataToSql() {
        baseContext.value?.let { that ->
            //探头温度和气压数据
            readProbeAllInfoEndList.forEach {
                //先删除数据，保证要上传只有一份
                DbHelper.init().getProbeRecordDao().delectProbeRecordList(it.mac,it.recordStartTime)
                it.probeSamplingRecordInfoList.map { item ->
                    item.mac = it.mac
                    item.recordStartTime = it.recordStartTime
                    item.recordSamplingInterval = it.recordSamplingInterval
                    item.wayNum = it.wayNum
                    item.wayIndex = it.wayIndex
                    val scaleNumber = BigDecimal(item.temperature / 100)
                    item.temperature = scaleNumber.setScale(2, RoundingMode.HALF_UP).toDouble()
                }
                //先存记录
                DbHelper.init().getProbeRecordDao().insertAll(it.probeSamplingRecordInfoList)
                val collectionEntity = CollectionEntity(
                    it.mac,
                    it.sw,
                    it.hw,
                    it.battery,
                    it.feature,
                    it.wayNum,
                    it.wayIndex,
                    it.recordSamplingInterval,
                    it.recordStartTime,
                    it.model,
                    it.recordNum
                )
                DbHelper.init().getCollectionDao().insert(collectionEntity)
                queueCollectionEntity.add(collectionEntity)
            }

            //一个一个传
            uploadProbeCollection(queueCollectionEntity.removeFirst())

        }
    }

    /**
     * 检测是否全部读取完成
     * @param probeStateInfos List<ProbeStateInfo>
     */
    fun onAllTestsCompleted(probeStateInfos: List<ProbeStateInfo>) {
        var isAllTestsCompleted = true
        for (item in probeStateInfos) {
            if (item.state != 3 && item.state != 0) {
                isAllTestsCompleted = false
            }
        }
        readCollectionBtn.set(isAllTestsCompleted)
    }

    //清除定时任务
    override fun onCleared() {
        super.onCleared()
        timer.cancel()
    }

    fun uploadProbeCollection(collectionEntity: CollectionEntity) {
        //离线不做上传
        if (UserCacheHelper.isOffline()){
            queueCollectionEntity.clear()
            loadingChange.dismissDialog.postValue(false)
            toast("读取采集数据操作完成")
            return
        }

        baseContext.value?.let { that ->
            request({
                HttpRequestCoroutine.uploadProbeCollection(
                    that, collectionEntity
                )
            }, {
                val nextCollectionEntity = queueCollectionEntity.removeFirstOrNull()
                if (nextCollectionEntity == null) {
                    loadingChange.dismissDialog.postValue(false)
                    toast("读取采集数据操作完成")
                } else {
                    uploadProbeCollection(nextCollectionEntity)
                }
                "上传成功".loge()
            }, {
                val nextCollectionEntity = queueCollectionEntity.removeFirstOrNull()
                if (nextCollectionEntity == null) {
                    loadingChange.dismissDialog.postValue(false)
                    toast("读取采集数据操作完成")
                } else {
                    uploadProbeCollection(nextCollectionEntity)
                }
                "上传失败".loge()
            })
        }

    }

    fun sendProbeInfoCommand(){
        //开始传输数据
        val removeFirst = queueProbeStateInfo.removeFirstOrNull()
        if (removeFirst == null) {
            sendProbeTestingInfoCommand()
            return
        }
        val uByteArray = removeFirst.probeMac.split(":")
            .map { value -> value.toUByte(16) }
            .toUByteArray()
        val generateGetProbeInfoRequestData =
            BleRequestData.generateGetProbeInfoRequestData(uByteArray)

        BleHelper.writeRetryWhen(generateGetProbeInfoRequestData,10,object : BleWriteListener() {
            override fun onWriteFail() {
                probeListState.value?.let {
                    for (item in it) {
                        if (TextUtils.equals(removeFirst.probeMac, item.probeMac)) {
                            item.state = 2
                            break
                        }
                    }
                    probeListState.postValue(it)
                    sendProbeInfoCommand()
                }
            }
        })
    }

    @OptIn(ExperimentalUnsignedTypes::class)
    fun sendProbeTestingInfoCommand(){

        val probeInfo = queueProbeTestingStateInfo.removeFirstOrNull()
        if (probeInfo == null) {
            loadingChange.dismissDialog.postValue(false)
        } else {
            //去获取读取采集信息
            val uByteArray = probeInfo.mac.split(":").map { value -> value.toUByte(16) }
                .toUByteArray()
            val generateGetProbeInfoRequestData =
                BleRequestData.generateReadSamplingInfoRequestData(
                    uByteArray,
                    probeInfo.currentSamplingTimes.toInt()
                )
            BleHelper.writeRetryWhen(
                generateGetProbeInfoRequestData,
                10,
                object : BleWriteListener() {

                })
        }

    }
}